package com.ycy.plugin;

import com.ycy.plugin.code.CodeAlgorithm;
import com.ycy.plugin.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * 对称算法
 */
public class AESAlgorithm extends SymmetricAlgorithm {

  private final static Logger LOGGER = LoggerFactory.getLogger(AESAlgorithm.class);

  public AESAlgorithm(String secretType, String dataSecret) {
    this.secretType = secretType;
    this.dataSecret = dataSecret;
    this.dataSecretiv = dataSecret;
  }

  public AESAlgorithm(String secretType, String dataSecret, String dataSecretiv, String out, String toCase) {
    this.secretType = secretType;
    this.dataSecret = dataSecret;
    this.dataSecretiv = dataSecretiv;
    this.out = out;
    this.toCase = toCase;
  }

  /**
   * 数据加密
   *
   * @param src 数据
   * @return
   */
  public String encrypt(String src) {
    try {
      byte[] dataSecretBytes = dataSecret.getBytes(StandardCharsets.UTF_8);
      SecretKeySpec secretKeySpec = new SecretKeySpec(dataSecretBytes, "AES");
      Cipher cipher = Cipher.getInstance(this.secretType);
      IvParameterSpec iv = new IvParameterSpec(dataSecretiv.getBytes(), 0, 16);//使用CBC模式，需要一个向量iv，可增加加密算法的强度1234567890123456
      cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
      byte[] encryptByte = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));

      String encryptStr = Config.hex.equalsIgnoreCase(this.out) ? CodeAlgorithm.HexEncode(encryptByte) : CodeAlgorithm.Base64Encode(encryptByte);

      if (Config.touppercase.equalsIgnoreCase(this.toCase)) {
        return encryptStr.toUpperCase();
      }
      if (Config.tolowercase.equalsIgnoreCase(this.toCase)) {
        return encryptStr.toLowerCase();
      }
      return encryptStr;
    } catch (Exception ex) {
      LOGGER.warn("fail {}", ex.getMessage(), ex);
      return null;
    }
  }

  /**
   * 数据解密
   *
   * @param src 加密数据
   */
  public String decrypt(String src) {
    try {
      byte[] raw = dataSecret.getBytes(StandardCharsets.UTF_8);
      SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
      Cipher cipher = Cipher.getInstance(this.secretType);
      IvParameterSpec iv = new IvParameterSpec(dataSecretiv.getBytes(), 0, 16);
      cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
      byte[] decodeByte = Config.hex.equalsIgnoreCase(this.out) ? CodeAlgorithm.HexDecode(src) : CodeAlgorithm.Base64Decode(src);
      byte[] decryptByte = cipher.doFinal(decodeByte);
      return new String(decryptByte, StandardCharsets.UTF_8);
    } catch (Exception ex) {
      LOGGER.warn("fail {}", ex.getMessage(), ex);
      //日志
      return null;
    }
  }

  public static void main(String[] args) {
    //我方发送给openApi的请求参数
    String a = "{\"test\":\"testRequest\"}";
    //拼接openApi请求第三方的请求报文（第三方请求openApi也是这种格式）
    String dataSecret = "1234567890abcdef";

    AESAlgorithm aesAlgorithm = new AESAlgorithm("AES/CBC/PKCS5Padding", dataSecret);

    //加密
    String s = aesAlgorithm.encrypt(a);
    System.out.println(s);

    String decrypt = aesAlgorithm.decrypt(s);
    System.out.println(decrypt);

    //加密
    String s1 = aesAlgorithm.encrypt(a);
    System.out.println(s1);

    //解密
    System.out.println(aesAlgorithm.decrypt(s1));

    //解密
    System.out.println(aesAlgorithm.decrypt(s1));
  }

}
